package oneplay.YonghongBITools.utils;

import com.union.api.TUnionTransInfo;
import com.union.api.UnionEsscAPI;
import org.apache.hc.client5.http.utils.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class SM4Util {
    private static final Logger logger = LoggerFactory.getLogger(SM4Util.class);
    private static final String sysId = PropertiesUtil.getProperty("encoderSysId");
    private static final String appId = PropertiesUtil.getProperty("encoderAppId");
    private static final List<String> ipList = Arrays.asList(PropertiesUtil.getProperty("encoderIP").split(","));
    private static final List<Integer> portList = toIntegerList(Arrays.asList(PropertiesUtil.getProperty("encoderPort").split(",")));
    private static final String zekName = PropertiesUtil.getProperty("zekName");


    public static String encrypt(String str) {
        TUnionTransInfo tti = UnionEncryptPlainData(zekName, strToHexString(str));
        return tti.getReturnBody().getData();
    }

    public static String decrypt(String str) {
        try {
            TUnionTransInfo tti = UnionDecryptEncData(zekName, str);
            return hexStringToString(tti.getReturnBody().getData());
        } catch (Exception e) {
            logger.error("Wrong SM4Util Encrypted Secret Code !!!");
            logger.error(e.getMessage(), e);
            return "";
        }
    }

    /**
     * 字符串列表转整型列表
     *
     * @param strList 字符串列表
     * @return 整型列表
     */
    private static List<Integer> toIntegerList(List<String> strList) {
        List<Integer> list = new ArrayList<>();
        for (String str : strList) {
            list.add(Integer.parseInt(str));
        }
        return list;
    }

    /**
     * 加密方法
     *
     * @param zekName -- 秘钥
     * @param data    -- 明文数据
     * @return TUnionTransInfo类，其中TUnionTransInfo.getReturnBody().getData()为密文数据
     */
    private static TUnionTransInfo UnionEncryptPlainData(String zekName, String data) {
        // 连接加密机平台，ipList-ip地址，portList-端口，5-超时时间（单位是秒）
        UnionEsscAPI uea = new UnionEsscAPI(ipList, portList, 5, sysId, appId);
        return uea.UnionEncryptPlainData(zekName, data, 0, null);
    }

    /**
     * 解密方法
     *
     * @param zekName -- 秘钥
     * @param encData -- 密文数据
     * @return TUnionTransInfo类，其中TUnionTransInfo.getReturnBody().getData()为明文数据
     */
    private static TUnionTransInfo UnionDecryptEncData(String zekName, String encData) {
        UnionEsscAPI uea = new UnionEsscAPI(ipList, portList, 5, sysId, appId);
        return uea.UnionDecryptEncData(zekName, encData, 0, null);
    }

    /**
     * 把字符串转换为16进制
     *
     * @param str 源字符串
     * @return 16进制字符串
     */
    private static String strToHexString(String str) {
        StringBuilder sb = new StringBuilder();
        if (null == str || str.length() == 0) {
            return null;
        }
        for (int i = 0; i < str.length(); i++) {
            int v = str.charAt(i);
            String hv = Integer.toHexString(v);
            sb.append(hv);
        }
        return sb.toString();
    }

    /**
     * 十六进制转换为字符串
     *
     * @param hexString 16进制字符串
     * @return 字符串
     */
    private static String hexStringToString(String hexString) {
        if (null == hexString || hexString.isEmpty()) {
            return null;
        }
        hexString = hexString.replace(" ", "");
        byte[] baKeyword = new byte[hexString.length() / 2];
        for (int i = 0; i < baKeyword.length; i++) {
            baKeyword[i] = (byte) (0xff & Integer.parseInt(hexString.substring(i * 2, i * 2 + 2), 16));
        }
        hexString = new String(baKeyword);
        return hexString;
    }

    /**
     * Charset case
     */
    public static String wrap(String str) {
        return Base64.encodeBase64String(str.getBytes(StandardCharsets.UTF_8));
    }

    /**
     * Charset case
     */
    public static String unwrap(String str) {
        return new String(Base64.decodeBase64(str), StandardCharsets.UTF_8);
    }

}